package com.ezlcp.form.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ezlcp.commons.base.db.BaseDao;
import com.ezlcp.commons.base.db.BaseService;
import com.ezlcp.commons.base.entity.JsonPage;
import com.ezlcp.commons.base.entity.JsonPageResult;
import com.ezlcp.commons.base.entity.JsonResult;
import com.ezlcp.commons.base.entity.QueryData;
import com.ezlcp.commons.constant.Constants;
import com.ezlcp.commons.constant.DataTypeEnum;
import com.ezlcp.commons.constant.LanguageEnum;
import com.ezlcp.commons.constant.StatusEnum;
import com.ezlcp.commons.service.impl.SuperServiceImpl;
import com.ezlcp.commons.tool.IdGenerator;
import com.ezlcp.commons.tool.StringUtils;
import com.ezlcp.commons.utils.ContextUtil;
import com.ezlcp.form.db.DBHelper;
import com.ezlcp.form.db.IDbClient;
import com.ezlcp.form.db.TableStatusEnum;
import com.ezlcp.form.entity.Entity;
import com.ezlcp.form.entity.EntityCol;
import com.ezlcp.form.entity.EntityIndex;
import com.ezlcp.form.mapper.EntityColMapper;
import com.ezlcp.form.mapper.EntityIndexMapper;
import com.ezlcp.form.mapper.EntityMapper;
import com.github.drinkjava2.jdialects.Type;
import com.github.drinkjava2.jdialects.model.ColumnModel;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import static com.ezlcp.commons.constant.Constants.COL_STATUS;
import static com.ezlcp.commons.constant.Constants.COL_TENANT_ID;

/**
 * [数据库中表的定义]业务服务类
 */
@Service
public class EntityServiceImpl extends SuperServiceImpl<EntityMapper, Entity> implements BaseService<Entity> {
    @Resource
    private EntityMapper entityMapper;

    @Lazy
    @Resource
    private EntityColMapper entityColMapper;

    @Resource
    private EntityIndexMapper entityIndexMapper;

    @Resource
    private SerialNoServiceImpl serialNoService;

    @Resource
    private LogService logService;

    /***
     * 分页查询引用实体表的数据
     * @param params 分页查询参数
     * @param entId 实体ID
     * @param lang 当前变速器
     * @param noDeleted 是否过滤掉删除的数据
     * @return com.ezlcp.commons.base.entity.JsonPageResult
     * @author Elwin ZHANG
     * @date 2023/12/20 14:59
     */
    public JsonPageResult selectRefEntRecord(QueryData params, String entId, String lang, boolean noDeleted) {
        var entity = getBaseMapper().selectById(entId);
        if (entity == null || entity.getStatus() != 1) {
            //引用的实体表不存在
            return JsonPageResult.getFail("dialog.refEntityInvalid");
        }
        var allCols = getEntityCols(entId);
        if (allCols == null || allCols.size() < 2) {
            //引用的实体表少于两个字段
            return JsonPageResult.getFail("dialog.refEntityNoCols");
        }
        JSONObject languageInfo = new JSONObject();
        //根据不同的语言，返回相关的显示信息
        if (LanguageEnum.zh_HK.name().equals(lang)) {
            languageInfo.put("entName", entity.getHkName());
        } else if (LanguageEnum.en.name().equals(lang)) {
            languageInfo.put("entName", entity.getEnName());
        } else {
            languageInfo.put("entName", entity.getEntName());
        }
        String key = params.getKey();
        String conditions = " and (";
        List<EntityCol> needCols = new ArrayList<>();
        String selectSql = "select ";
        for (var col : allCols) {
            if (col.getMainCol() == 1 || col.getIsPk() == 1) {
                needCols.add(col);
                languageInfo.put(col.getFieldName(), getShowColName(col, lang));
                selectSql += col.getFieldName() + ",";
                if (StringUtils.isNotEmpty(key) && col.getIsPk() != 1 && DataTypeEnum.VarChar.getValue().equals(col.getColType())) {
                    conditions += col.getFieldName() + " like '%" + key + "%' or ";
                }
            }
        }
        //如果没有配置主要列，则从前面取一个非主键列来显示
        if (needCols.size() == 1) {
            for (var col : allCols) {
                if (col.getIsPk() != 1) {
                    needCols.add(col);
                    languageInfo.put(col.getFieldName(), getShowColName(col, lang));
                    selectSql += col.getFieldName() + ",";
                    if (StringUtils.isNotEmpty(key) && DataTypeEnum.VarChar.getValue().equals(col.getColType())) {
                        conditions += col.getFieldName() + " like '%" + key + "%' or ";
                    }
                    break;
                }
            }
        }
        selectSql = selectSql.substring(0, selectSql.length() - 1);
        selectSql += " from " + entity.getTableName() + " where 1=1 ";
        String countSql = "select count(*) from " + entity.getTableName() + " where 1=1 ";
        //如果有租户ID字段，则需要过滤当前租户ID
        if (hasTenantId(allCols)) {
            String tenantId = ContextUtil.getCurrentTenantId();
            if (StringUtils.isEmpty(tenantId)) {
                selectSql += " and (tenant_id is null or tenant_id='') ";
                countSql += " and (tenant_id is null or tenant_id='') ";
            } else {
                selectSql += " and tenant_id='" + tenantId + "' ";
                countSql += " and tenant_id='" + tenantId + "' ";
            }
        }
        if (noDeleted) {
            selectSql += "and status<4";
            countSql += "and status<4";
        }
        if (conditions.length() > 6) {
            conditions = conditions.substring(0, conditions.length() - 3);
            conditions += ") ";
            countSql += conditions;
            selectSql += conditions;
        }

        if (StringUtils.isNotEmpty(params.getSortField())) {
            selectSql += " order by " + params.getSortField();
            if (StringUtils.isNotEmpty(params.getSortOrder())) {
                selectSql += " " + params.getSortOrder();
            }
        }
        JsonPageResult result = JsonPageResult.getSuccess("common.handleSuccess");
        JSONObject data = new JSONObject();
        data.put("languageInfo", languageInfo);
        data.put("colInfo", needCols);
        result.setData(data);

        var client = DBHelper.getDbClient(entity.getDsId());
        var jdbcTemplate = client.getJdbcTemplate();
        var count = jdbcTemplate.queryForObject(countSql, Long.class);
        Long pageSize = params.getPageSize().longValue();
        Long pageNo = params.getPageNo().longValue();
        JsonPage page = new JsonPage(pageSize, pageNo, count);
        //要获取的分页记录数据超过总数量
        if (count <= pageSize * (params.getPageNo() - 1)) {
            result.setResult(page);
            return result;
        }
        //查询自定义实体的分页记录
        String sql = client.getPagedSql(selectSql, pageNo.intValue(), pageSize.intValue());
        var list = jdbcTemplate.queryForList(sql);
        page.setData(list);
        result.setResult(page);
        return result;
    }

    /***
     * 查询一条自定义实体表记录
     * @param entId 实体ID
     * @param pkId 记录ID
     * @return com.ezlcp.commons.base.entity.JsonResult
     * @author Elwin ZHANG
     * @date 2023/12/25 17:35
     */
    public JsonResult getRefEntityShowText(String entId, String pkId) {
        var entity = this.getBaseMapper().selectById(entId);
        if (entity == null) {
            return JsonResult.Fail("common.paramError");
        }
        var result = JsonResult.Success("common.handleSuccess");
        var client = DBHelper.getDbClient(entity.getDsId());
        var formData = client.getById(entity.getTableName(), pkId);

        //查出实体的第一个主要列
        if (formData != null && !formData.isEmpty()) {
            String showFieldName = "";
            var allCols = getEntityCols(entId);
            for (var col : allCols) {
                if (col.getMainCol() == 1) {
                    showFieldName = col.getFieldName();
                    break;
                }
            }
            if (StringUtils.isEmpty(showFieldName)) {
                showFieldName = allCols.get(1).getFieldName();
            }
            result.setData(formData.get(showFieldName));
        }

        return result;
    }

    /***
     * 实列列中是否含用租户ID字段
     * @param cols 实体列
     * @return boolean
     */
    private boolean hasTenantId(List<EntityCol> cols) {
        if (cols == null || cols.isEmpty()) {
            return false;
        }
        for (var col : cols) {
            if (Constants.COL_TENANT_ID.equals(col.getFieldName())) {
                return true;
            }
        }
        return false;
    }

    /***
     * 根据当前的语言返回要显示的列名
     * @param col 实体列
     * @param lang 当前语言
     */
    private String getShowColName(EntityCol col, String lang) {
        if (LanguageEnum.zh_HK.name().equals(lang)) {
            return col.getHkName();
        } else if (LanguageEnum.en.name().equals(lang)) {
            return col.getEnName();
        } else {
            return col.getShowName();
        }
    }

    /***
     * 判断数据源是否被 实体引用
     * @param dsId 数据源ID
     * @return boolean
     */
    public boolean isDataSourceUsed(String dsId) {
        if (StringUtils.isEmpty(dsId)) {
            return true;
        }
        var wrapper = new LambdaQueryWrapper<Entity>();
        wrapper.eq(Entity::getDsId, dsId).lt(Entity::getStatus, 4);
        return this.entityMapper.exists(wrapper);
    }

    /***
     * @description 从数据库中的表或视图逆向生成实体
     * @param dsId 数据源ID
     * @param tableName 表名或视图名
     * @param moduleId 所属模块ID
     * @return com.ezlcp.commons.base.entity.JsonResult
     */
    @Transactional
    public JsonResult createFromDB(String dsId, String tableName, String moduleId) {
        var client = DBHelper.getDbClient(dsId);
        var tableModel = client.getTableModel(tableName);
        if (tableModel == null || tableModel.getColumns().isEmpty()) {
            return JsonResult.Fail("entity.notExists");
        }
        String tenantId = ContextUtil.getCurrentTenantId();
        //创建实体对象
        Entity entity = new Entity();
        String entId = IdGenerator.getIdStr();
        entity.setEntId(entId);
        entity.setTableName(tableName);
        String tableComment = tableModel.getComment();
        entity.setEntName(tableName);
        if (StringUtils.isNotEmpty(tableComment)) {
            if (tableComment.length() <= 30) {
                entity.setEntName(tableComment);
            } else {
                entity.setEnName(tableComment.substring(0, 29));
            }
        }
        entity.setModuleId(moduleId);
        entity.setDsId(dsId);
        entity.setIsBuildIn(Constants.SHORT0);
        entity.setStatus(Constants.SHORT0);
        entity.setIsGenDb(Constants.SHORT0);
        entity.setIsLogicDel(Constants.SHORT0);
        entity.setGenLog(Constants.SHORT0);
        entity.setIsFromDb(Constants.SHORT1);
        entity.setSeq(1);
        entity.setTenantId(tenantId);
        entity.setRemark("由数据库逆向生成；Create from Database");
        entityMapper.insert(entity);
        //循环创建实体字段
        short i = 1;
        for (var col : tableModel.getColumns()) {
            insertColFromDB(col, entId, tenantId, i++);
        }
        var result = JsonResult.Success("common.handleSuccess");
        return result;
    }

    /***
     * @description 插入实体列
     * @param columnModel 从数据库获取的列模型
     * @param entId 实体ID
     * @param tenantId 租户ID
     * @param index 顺序号
     */
    private void insertColFromDB(ColumnModel columnModel, String entId, String tenantId, short index) {
        EntityCol col = new EntityCol();
        col.setColId(IdGenerator.getIdStr());
        col.setEntId(entId);
        col.setTenantId(tenantId);
        String modelColName = columnModel.getColumnName();
        col.setFieldName(modelColName);
        col.setShowName(modelColName);
        String comment = columnModel.getComment();
        if (StringUtils.isNotEmpty(comment)) {
            if (comment.length() <= 30) {
                col.setShowName(comment);
            } else {
                col.setShowName(comment.substring(0, 29));
            }
        }
        col.setIsBuildIn(Constants.SHORT0);
        int length = columnModel.getLength() == null ? 0 : columnModel.getLength();
        col.setColLength((short) length);
        var dataType = columnModel.getColumnType();
        col.setColType(DataTypeEnum.VarChar.getValue());
        if (Type.SMALLINT.equals(dataType) || Type.TINYINT.equals(dataType) || Type.BIT.equals(dataType) || Type.BOOLEAN.equals(dataType)) {
            col.setColType(DataTypeEnum.SmallInt.getValue());
        } else if (Type.INTEGER.equals(dataType) || Type.INT.equals(dataType)) {
            col.setColType(DataTypeEnum.Int.getValue());
        } else if (Type.BIGINT.equals(dataType)) {
            col.setColType(DataTypeEnum.BigInt.getValue());
        } else if (Type.DECIMAL.equals(dataType) || Type.NUMERIC.equals(dataType) || Type.REAL.equals(dataType) || Type.DOUBLE.equals(dataType) || Type.FLOAT.equals(dataType)) {
            col.setColType(DataTypeEnum.Decimal.getValue());
        } else if (Type.DATE.equals(dataType)) {
            col.setColType(DataTypeEnum.Date.getValue());
        } else if (Type.DATETIME.equals(dataType) || Type.TIMESTAMP.equals(dataType) || Type.TIME.equals(dataType)) {
            col.setColType(DataTypeEnum.Datetime.getValue());
        } else if (Type.LONGTEXT.equals(dataType) || Type.MEDIUMTEXT.equals(dataType) || Type.LONGBLOB.equals(dataType) || Type.MEDIUMBLOB.equals(dataType)) {
            col.setColType(DataTypeEnum.LongText.getValue());
        } else if (Type.CLOB.equals(dataType) || Type.TEXT.equals(dataType) || Type.NCLOB.equals(dataType) || Type.BLOB.equals(dataType)
                || Type.BINARY.equals(dataType) || Type.LONGVARBINARY.equals(dataType) || Type.VARBINARY.equals(dataType) || length > 8000) {
            col.setColType(DataTypeEnum.Text.getValue());
        }
        int prec = columnModel.getScale() == null ? 0 : columnModel.getScale();
        col.setColPrec((short) prec);
        col.setColOrder(index);
        col.setIsRequired(columnModel.getNullable() ? Constants.SHORT0 : Constants.SHORT1);
        col.setIsPk(columnModel.getPkey() ? Constants.SHORT1 : Constants.SHORT0);
        col.setDefaultVal(columnModel.getDefaultValue());
        col.setSeq(1);
        entityColMapper.insert(col);
    }

    /***
     * @description 发布实体
     * @param entId 实体ID
     * @return com.ezlcp.commons.base.entity.JsonResult
     * @author Elwin ZHANG
     * @date 2023/7/13 16:21
     */
    @Transactional
    public JsonResult publishEntity(String entId) {
        Entity entity = this.get(entId);
        if (entity == null || entity.getCols().isEmpty() || entity.getIsBuildIn() == 1
                || entity.getStatus() == StatusEnum.deleted.getValue()) {
            return JsonResult.Fail("common.paramError");
        }
        logService.saveSystemLog("实体管理", "publish", entId, null);
        var client = DBHelper.getDbClient(entity.getDsId());
        //不生成物理表
        if (entity.getIsGenDb() == 0) {
            publish(entity);
            return JsonResult.Success("common.handleSuccess");
        }
        int exist = client.existTable(entity);

        //1.表不存在,直接创建
        if (exist == TableStatusEnum.NotExist.getValue()) {
            client.createTable(entity);
            publish(entity);
            publishIndex(entity, client, true);
            return JsonResult.Success("common.handleSuccess");
        }
        //第一次发布，表却已经存在
        if (entity.getStatus() == StatusEnum.disable.getValue()) {
            //数据库中已存在同名表，请修改表名后再发布！
            return JsonResult.Fail("entity.tableExists");
        }
        //2.空的表，先删除再创建
        if (exist == TableStatusEnum.Empty.getValue()) {
            client.dropTable(entity);
            client.createTable(entity);
            publish(entity);
            publishIndex(entity, client, true);
            return JsonResult.Success("common.handleSuccess");
        }

        //3.表已经存在数据的，再次发布的情况
        var sqlArr = client.alterTableSql(entity);
        //表结构没有变化，不用修改
        if (sqlArr == null || sqlArr.length == 0) {
            publish(entity);
            publishIndex(entity, client, false);
            return JsonResult.Success("entity.notChange");
        }
        //没有删除字段，只是增加字段，直接执行
        if (!client.containDropSql(sqlArr)) {
            client.executeSql(sqlArr);
            publish(entity);
            publishIndex(entity, client, false);
            return JsonResult.Success("common.handleSuccess");
        }
        //有数据且要删除列，返回手动执行
        //物理表已有数据，请检查并手动执行以下SQL语句，以防数据丢失。
        var result = JsonResult.Success("entity.manually");
        result.setData(sqlArr);
        publishIndex(entity, client, false);
        return result;
    }

    /***
     * @description 发布索引
     * @param entity 实体对象
     * @param rebuild 是否重新建表了
     */
    private void publishIndex(Entity entity, IDbClient client, boolean rebuild) {
        //是否需要修改索引
        var lstIndexes = entity.getIndexes();
        if (lstIndexes == null || lstIndexes.isEmpty()) {
            return;
        }
        String tableName = entity.getTableName();
        for (var index : lstIndexes) {
            //已创建的索引，跳过
            if (index.getStatus() == StatusEnum.enable.getValue() && !rebuild) {
                continue;
            }
            //删除索引
            if (!rebuild) {
                client.dropIndex(index.getIndexName(), tableName);
            }

            //创建索引
            if (index.getStatus() != StatusEnum.deleted.getValue()) {
                client.createIndex(index, tableName);
                index.setStatus(Constants.SHORT1);
                index.setSeq(index.getSeq() + 1);
                this.entityIndexMapper.updateById(index);
            } else {
                //删除索引执行后，删除对应的记录
                this.entityIndexMapper.deleteById(index);
            }
        }
    }

    /***
     * @description 实体发布
     * @param entity 实体对象
     */
    private void publish(Entity entity) {
        entity.setStatus(Constants.SHORT1);
        entity.setSeq(entity.getSeq() + 1);
        this.updateById(entity);
    }

    /***
     * @description 选择字段关联的实体
     * @param entId 原实体ID
     * @return java.util.List<com.ezlcp.form.entity.Entity>
     * @author Elwin ZHANG
     * @date 2023/8/18 14:04
     */
    public List<Entity> selectEntity(String entId) {
        QueryWrapper<Entity> wrapper = new QueryWrapper<>();
        String tenantId = ContextUtil.getCurrentTenantId();
        if (StringUtils.isEmpty(tenantId)) {
            wrapper.and(query -> query.eq(COL_TENANT_ID, "").or().isNull(COL_TENANT_ID));
        } else {
            wrapper.eq(COL_TENANT_ID, tenantId);
        }
        wrapper.eq(COL_STATUS, StatusEnum.enable.getCode());
        if (StringUtils.isNotEmpty(entId)) {
            wrapper.lambda().ne(Entity::getEntId, entId);
        }
        wrapper.lambda().orderByDesc(Entity::getCreateTime);
        return this.entityMapper.selectList(wrapper);
    }

    /***
     * @description 查询某模块下的实体
     * @param moduleId 原实体ID
     * @return java.util.List<com.ezlcp.form.entity.Entity>
     */
    public List<Entity> selectByModuleId(String moduleId) {
        QueryWrapper<Entity> wrapper = new QueryWrapper<>();
        String tenantId = ContextUtil.getCurrentTenantId();
        if (StringUtils.isEmpty(tenantId)) {
            wrapper.and(query -> query.eq(COL_TENANT_ID, "").or().isNull(COL_TENANT_ID));
        } else {
            wrapper.eq(COL_TENANT_ID, tenantId);
        }
        wrapper.eq(COL_STATUS, StatusEnum.enable.getCode());
        wrapper.lambda().eq(Entity::getModuleId, moduleId).eq(Entity::getIsBuildIn, 0).orderByDesc(Entity::getCreateTime);
        return this.entityMapper.selectList(wrapper);
    }

    /***
    * 根据实体ID查询出实体和实体列
    * @param entId 实体ID
    */
    public Entity getEntityAndCols(String entId) {
        var entity = BaseService.super.get(entId);
        if (entity != null) {
            var list = getEntityCols(entity.getEntId());
            entity.setCols(list);
        }
        return entity;
    }

    @Override
    public Entity get(Serializable id) {
        var entity = BaseService.super.get(id);
        if (entity != null) {
            var list = getEntityCols(entity.getEntId());
            if (list != null && list.size() > 0) {
                getColRefEntName(list);
                getColRefOrderName(list);
                entity.setCols(list);
            }
            QueryWrapper<EntityIndex> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(EntityIndex::getEntId, entity.getEntId()).orderByAsc(EntityIndex::getCreateTime);
            var list2 = entityIndexMapper.selectList(queryWrapper);
            entity.setIndexes(list2);
        }
        return entity;
    }

    /***
     * 查询实体的所有有字段
     * @param entId 字体ID
     * @return java.util.List<com.ezlcp.form.entity.EntityCol>
     */
    public List<EntityCol> getFields(String entId) {
        QueryWrapper<EntityCol> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(EntityCol::getFieldName, EntityCol::getShowName, EntityCol::getHkName, EntityCol::getEnName)
                .eq(EntityCol::getEntId, entId);
        return entityColMapper.selectList(queryWrapper);
    }

    /***
     * 查询实体的字段信息
     * @param entId 实体ID
     */
    public List<EntityCol> getEntityCols(String entId) {
        QueryWrapper<EntityCol> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(EntityCol::getEntId, entId).orderByAsc(EntityCol::getColOrder);
        return entityColMapper.selectList(wrapper);
    }

    /***
     * @description 查询出字段引用的实体名
     * @param cols 字段列表
     * @author Elwin ZHANG
     * @date 2023/6/28 17:54
     */
    private void getColRefEntName(List<EntityCol> cols) {
        for (var col : cols) {
            String refId = col.getRefEntId();
            if (StringUtils.isEmpty(refId)) {
                continue;
            }
            var refEnt = entityMapper.selectById(refId);
            if (refEnt != null) {
                col.setRefEntName(refEnt.getEntName());
                col.setRefEnName(refEnt.getEnName());
                col.setRefHkName(refEnt.getHkName());
            }
        }
    }


    /***
     * @description 查询出字段关联单据编号名称
     * @param cols 字段列表
     */
    private void getColRefOrderName(List<EntityCol> cols) {
        for (var col : cols) {
            String orderNoId = col.getRefSerialNo();
            if (StringUtils.isEmpty(orderNoId)) {
                continue;
            }
            var orderNo = serialNoService.getBaseMapper().selectById(orderNoId);
            if (orderNo != null) {
                col.setRefOrderName(orderNo.getOrderName());
                col.setRefEnOrderName(orderNo.getEnName());
                col.setRefHkOrderName(orderNo.getHkName());
            }
        }
    }

    /***
     * @description 保存实体表及列定义
     * @param ent 实体
     * @param delIds 要删除的列ID
     * @return java.lang.String
     * @author Elwin ZHANG
     * @date 2023/6/28 11:21
     */
    @Transactional
    public String saveEntity(Entity ent, String delIds) {
        String tenantId = ContextUtil.getCurrentTenantId();
        //主表是新增
        if (StringUtils.isEmpty(ent.getEntId())) {
            ent.setTenantId(tenantId);
            ent.setEntId(IdGenerator.getIdStr());
            ent.setIsBuildIn(Constants.SHORT0);
            this.entityMapper.insert(ent);
        } else {
            //主表是编辑
            var oldEnt = this.entityMapper.selectById(ent.getEntId());
            if (oldEnt.getSeq() != ent.getSeq()) {
                return "common.dataChange";
            }
            ent.setSeq(ent.getSeq() + 1);
            this.entityMapper.updateById(ent);
        }
        String entId = ent.getEntId();
        String strCols = JSON.toJSONString(ent.getCols());
        var cols = JSONArray.parseArray(strCols, EntityCol.class);
        //循环处理字段定义
        for (var col : cols) {
            col.setEntId(entId);
            //新增字段
            if (StringUtils.isEmpty(col.getColId())) {
                col.setColId(IdGenerator.getIdStr());
                col.setTenantId(tenantId);
                entityColMapper.insert(col);
            } else {
                //修改字段
                col.setSeq(col.getSeq() + 1);
                entityColMapper.updateById(col);
            }
        }
        //循环处理索引
        if (ent.getIndexes() != null && !ent.getIndexes().isEmpty()) {
            String strIndexes = JSON.toJSONString(ent.getIndexes());
            var indexes = JSONArray.parseArray(strIndexes, EntityIndex.class);
            for (var index : indexes) {
                index.setEntId(entId);
                //新增
                if (StringUtils.isEmpty(index.getId())) {
                    index.setId(IdGenerator.getIdStr());
                    index.setTenantId(tenantId);
                    entityIndexMapper.insert(index);
                    continue;
                }
                //删除状态
                if (index.getStatus() == StatusEnum.deleted.getValue()) {
                    var oldIndex = entityIndexMapper.selectById(index.getId());
                    //原来未生效的索引，直接删除
                    if (oldIndex.getStatus() == StatusEnum.disable.getValue()) {
                        entityIndexMapper.deleteById(oldIndex);
                        continue;
                    }
                }
                //修改
                index.setSeq(index.getSeq() + 1);
                entityIndexMapper.updateById(index);
            }
        }
        //是否有要删除的子记录
        ArrayList<String> delFields = new ArrayList<>();
        if (StringUtils.isNotEmpty(delIds)) {
            String[] ids = delIds.split(",");
            for (String id : ids) {
                if (StringUtils.isEmpty(id)) {
                    continue;
                }
                var oldCol = entityColMapper.selectById(id);
                if (oldCol != null && oldCol.getIsBuildIn() != 1
                        && StringUtils.compare(tenantId, oldCol.getTenantId()) == 0) {
                    delFields.add(oldCol.getFieldName());
                    entityColMapper.deleteById(id);
                }
            }
        }
        return "";
    }

    /***
     * @description 获取自定义实体固定字段（必须有，不能删除和修改）
     * @return java.util.List<com.ezlcp.form.entity.EntityCol>
     * @author Elwin ZHANG
     * @date 2023/6/27 10:26
     */
    public List<EntityCol> getFixedCols() {
        String remark = "默认字段，Default Field";
        ArrayList<EntityCol> list = new ArrayList<>();
        //ID
        EntityCol col = new EntityCol();
        col.setFieldName(Constants.COL_ID);
        col.setShowName("主键");
        col.setHkName("主鍵");
        col.setEnName("Id");
        col.setColType(DataTypeEnum.VarChar.getValue());
        col.setColLength((short) 64);
        col.setRemark(remark);
        col.setIsPk(Constants.SHORT1);
        col.setColOrder(Constants.SHORT1);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //状态
        col = new EntityCol();
        col.setFieldName(Constants.COL_STATUS);
        col.setShowName("状态");
        col.setHkName("狀態");
        col.setEnName("Status");
        col.setColType(DataTypeEnum.Int.getValue());
        col.setRemark(remark);
        col.setDefaultVal("0");
        col.setColOrder((short) 991);
        col.setIsBuildIn(Constants.SHORT1);
        col.setIsRequired(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT1);
        list.add(col);

        //租户ID
        col = new EntityCol();
        col.setFieldName(Constants.COL_TENANT_ID);
        col.setShowName("租户ID");
        col.setHkName("租戶ID");
        col.setEnName("Tenant Id");
        col.setColType(DataTypeEnum.VarChar.getValue());
        col.setColLength((short) 64);
        col.setRemark(remark);
        col.setColOrder((short) 992);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //创建人
        col = new EntityCol();
        col.setFieldName(Constants.COL_CREATE_BY);
        col.setShowName("创建人");
        col.setHkName("創建人");
        col.setEnName("Create By");
        col.setColType(DataTypeEnum.VarChar.getValue());
        col.setColLength((short) 64);
        col.setRemark(remark);
        col.setColOrder((short) 993);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //创建时间
        col = new EntityCol();
        col.setFieldName(Constants.COL_CREATE_TIME);
        col.setShowName("创建时间");
        col.setHkName("創建時間");
        col.setEnName("Create Time");
        col.setColType(DataTypeEnum.Datetime.getValue());
        col.setRemark(remark);
        col.setColOrder((short) 994);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //最后修改人
        col = new EntityCol();
        col.setFieldName(Constants.COL_UPDATE_BY);
        col.setShowName("最后修改人");
        col.setHkName("最後修改人");
        col.setEnName("Update By");
        col.setColType(DataTypeEnum.VarChar.getValue());
        col.setColLength((short) 64);
        col.setRemark(remark);
        col.setColOrder((short) 995);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //最后修改时间
        col = new EntityCol();
        col.setFieldName(Constants.COL_UPDATE_TIME);
        col.setShowName("最后修改时间");
        col.setHkName("最後修改時間");
        col.setEnName("Update Time");
        col.setColType(DataTypeEnum.Datetime.getValue());
        col.setRemark(remark);
        col.setColOrder((short) 996);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);

        //修改次数
        col = new EntityCol();
        col.setFieldName(Constants.COL_SEQ);
        col.setShowName("修改次数");
        col.setHkName("修改次數");
        col.setEnName("Edit times");
        col.setColType(DataTypeEnum.Int.getValue());
        col.setRemark(remark);
        col.setColOrder((short) 997);
        col.setIsBuildIn(Constants.SHORT1);
        col.setCanSearch(Constants.SHORT0);
        list.add(col);
        return list;
    }

    /***
     * @description 逻辑删除实体
     * @param entId 实体ID
     * @author Elwin ZHANG
     * @date 2023/6/14 15:18
     */
    public void delEntity(String entId, boolean delTable) {
        var entity = this.entityMapper.selectById(entId);
        if (entity == null) {
            return;
        }
        if (entity.getStatus() == StatusEnum.deleted.getValue() || entity.getIsBuildIn() == 1) {
            return;
        }
        //删除物理表
        if (delTable && entity.getIsGenDb() == 1) {
            var client = DBHelper.getDbClient(entity.getDsId());
            client.dropTable(entity);
        }
        entity.setStatus((short) StatusEnum.deleted.getValue());
        entity.setSeq(entity.getSeq() + 1);
        this.entityMapper.updateById(entity);
    }

    /***
     * @description 检查物理表名是否存在
     * @param tableName 物理表名
     * @param entId 当前记录ID
     * @param dsId 数据源ID
     * @return boolean
     * @author Elwin ZHANG
     * @date 2023/6/14 11:04
     */
    public boolean checkTableName(String tableName, String entId, String dsId) {
        QueryWrapper<Entity> wrapper = new QueryWrapper();
        wrapper.lambda().eq(Entity::getTableName, tableName).
                lt(Entity::getStatus, StatusEnum.deleted.getValue());
        if (StringUtils.isNotEmpty(entId)) {
            wrapper.lambda().ne(Entity::getEntId, entId);
        }
        if (StringUtils.isNotEmpty(dsId)) {
            wrapper.lambda().eq(Entity::getDsId, dsId);
        } else {
            wrapper.lambda().eq(Entity::getDsId, "");
        }
        var cnt = this.entityMapper.selectCount(wrapper);
        if (cnt != null && cnt > 0) {
            return true;
        }
        return false;
    }

    @Override
    public BaseDao<Entity> getRepository() {
        return entityMapper;
    }
}